/* autor Konjkov@gmail.ru */

#include <stdio.h>
#include <string.h>

#include "table.h"
#include "common.h"

int table_add(char *name) {
SQLHSTMT stmt;
SQLRETURN retcode;
char buffer[MAX_STATEMENT_LEN];
char allfields[MAX_NAME_LEN*64];
char allvalues[MAX_NAME_LEN*64];
char allfieldsdef[MAX_NAME_LEN*64];
char owner[MAX_NAME_LEN];
char table[MAX_NAME_LEN];

int  i = 0;
int  j = 0;
int  k = 0;

SQLCHAR       ColumnName[MAX_NAME_LEN], TypeName[MAX_NAME_LEN];
SQLINTEGER    ColumnSize;
SQLSMALLINT   DataType, DecimalDigits;
SQLLEN        ColumnNameSize, DataTypeSize, TypeNameSize, ColumnSizeSize, DecimalDigitsSize;

    sscanf(name, "%[^.].%s", owner, table);

    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLColumns( stmt, NULL, 0, owner, SQL_NTS, table, SQL_NTS, NULL, 0) );

    SQLBindCol( stmt, 4, SQL_C_CHAR, ColumnName, MAX_NAME_LEN, &ColumnNameSize);
    SQLBindCol( stmt, 5, SQL_C_SSHORT, &DataType, 0, &DataTypeSize);
    SQLBindCol( stmt, 6, SQL_C_CHAR, TypeName, MAX_NAME_LEN, &TypeNameSize);
    SQLBindCol( stmt, 7, SQL_C_SLONG, &ColumnSize, 0, &ColumnSizeSize);
    SQLBindCol( stmt, 9, SQL_C_SSHORT, &DecimalDigits, 0, &DecimalDigitsSize);
    while(1) {
        retcode = SQLFetch(stmt);
        if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
            if ( strcmp( ColumnName, "packet") && strcmp( ColumnName, "initpacket") ) {
                    i += sprintf(allfields + i, "%s,", ColumnName);
                    j += sprintf(allvalues + j, SQL_FIELDPREFIX_OLD".%s,", ColumnName);
                switch (DataType) {
                case SQL_NUMERIC:
                    k += sprintf(allfieldsdef + k, "%s %s(%i,%i),", ColumnName, TypeName, ColumnSize, DecimalDigits);
                    break;
                case SQL_CHAR:
                    k += sprintf(allfieldsdef + k, "%s %s(%i),", ColumnName, "char", ColumnSize);
                    break;
                case SQL_VARCHAR:
                    k += sprintf(allfieldsdef + k, "%s %s(%i),", ColumnName, "varchar", ColumnSize);
                    break;
                default:
                    k += sprintf(allfieldsdef + k, "%s %s,", ColumnName, TypeName);
                    break;
                }
            }
        } else if (retcode == SQL_NO_DATA){
            allfields[i-1] = '\0';
            allvalues[j-1] = '\0';
            allfieldsdef[k-1] = '\0';
            break;
        } else {
            return syncctl_error( stmt , __FILE__, __LINE__);
        }
    }
    SQLFreeStmt( stmt, SQL_CLOSE );

    table_remove(name);

    sprintf( buffer, "ALTER TABLE %s.%s ADD "SQL_SYSFIELD1" integer DEFAULT 0 NOT NULL", owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, "ALTER TABLE %s.%s ADD "SQL_SYSFIELD2" integer DEFAULT 0 NOT NULL", owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, "CREATE INDEX i_%s_%s_"SQL_SYSFIELD1" ON %s.%s("SQL_SYSFIELD1")", owner, table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_FUNCTION_BU1, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_TRIGGER_BU1, table, owner, table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_FUNCTION_BU2, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_TRIGGER_BU2, table, owner, table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_WATCHDELETE_TABLE, owner, table, allfieldsdef);
    SQLAllocStmt( dbc, &stmt );

    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_WATCHDELETE_FUNCTION, owner, table, owner, table, allfields, allvalues);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    sprintf( buffer, SQL_WATCHDELETE_TRIGGER, table, owner, table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, buffer, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    return 0;
}

int table_remove(char *name) {
SQLHSTMT stmt;
char buffer[MAX_STATEMENT_LEN];
char owner[MAX_NAME_LEN];
char table[MAX_NAME_LEN];

    sscanf(name, "%[^.].%s", owner, table);
// SQL-скрипт выключения таблицы из процесса синхронизации

//    DROP TRIGGER zzz_<table>_sync_ad ON <owner>.<table>;
    sprintf( buffer, "DROP TRIGGER %s_sync_ad ON %s.%s", table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP FUNCTION <owner>.<table>_sync_func_ad();
    sprintf( buffer, "DROP FUNCTION %s.%s_sync_func_ad()", owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP TRIGGER zz_<table>_sync_bu1 ON <owner>.<table>;
    sprintf( buffer, "DROP TRIGGER %s_sync_bu1 ON %s.%s", table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP FUNCTION <owner>.<table>_sync_func_bu1();
    sprintf( buffer, "DROP FUNCTION %s.%s_sync_func_bu1()", owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP TRIGGER zzz_<table>_sync_bu2 ON <owner>.<table>;
    sprintf( buffer, "DROP TRIGGER %s_sync_bu2 ON %s.%s", table, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP FUNCTION <owner>.<table>_sync_func_bu2();
    sprintf( buffer, "DROP FUNCTION %s.%s_sync_func_bu2()", owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP INDEX <owner>.i_<owner>_<table>_SQL_SYSFIELD1;
    sprintf( buffer, "DROP INDEX %s.i_%s_%s_"SQL_SYSFIELD1, owner, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    ALTER TABLE <owner>.<table> DROP SQL_SYSFIELD1;
    sprintf( buffer, "ALTER TABLE %s.%s DROP "SQL_SYSFIELD1, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    ALTER TABLE <owner>.<table> DROP SQL_SYSFIELD2;
    sprintf( buffer, "ALTER TABLE %s.%s DROP "SQL_SYSFIELD2, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP TABLE <owner>.<table>_SQL_PREFIX_DELTABLE;
    sprintf( buffer, "DROP TABLE %s.%s_"SQL_PREFIX_DELTABLE, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }
//    DROP TABLE <owner>.<table>_SQL_PREFIX_UNLOADTABLE;
    sprintf( buffer, "DROP TABLE %s.%s_"SQL_PREFIX_UNLOADTABLE, owner, table);
    SQLAllocStmt( dbc, &stmt );
    if ( !SQL_SUCCEEDED( SQLExecDirect( stmt, buffer, SQL_NTS ) ) ) {
        syncctl_error( stmt , __FILE__, __LINE__);
    } else {
        SQLFreeStmt( stmt, SQL_CLOSE );
    }

    return 0;
}

int table_update(char *name) {
char owner[MAX_NAME_LEN];
char table[MAX_NAME_LEN];

    sscanf(name, "%[^.].%s", owner, table);

    return 0;
}

int table_dwatch_on(char *name) {
SQLHSTMT stmt;
SQLRETURN retcode;
char owner[MAX_NAME_LEN];
char table[MAX_NAME_LEN];

    sscanf(name, "%[^.].%s", owner, table);

    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, SQL_WATCHDELETE_TABLE, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, SQL_WATCHDELETE_FUNCTION, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    SQLAllocStmt( dbc, &stmt );
    EXEC_SQL( SQLExecDirect( stmt, SQL_WATCHDELETE_TRIGGER, SQL_NTS ) );
    SQLFreeStmt( stmt, SQL_CLOSE );

    return 0;
}

int table_dwatch_off(char *name) {
char owner[MAX_NAME_LEN];
char table[MAX_NAME_LEN];

    sscanf(name, "%[^.].%s", owner, table);

    return 0;
}
